package buffer

import (
	"context"
	"encoding/json"
	"fmt"
	"laundry-service/entity"
	"time"

	"github.com/go-redis/redis/v8"
	"github.com/zeromicro/go-zero/core/logx"
)

type ProductCache struct {
	client *redis.Client
	ctx    context.Context
}

func NewProductCache(client *redis.Client) *ProductCache {
	return &ProductCache{
		client: client,
		ctx:    context.Background(),
	}
}

func (pc *ProductCache) getProductKey(productId int) string {
	return fmt.Sprintf("product:%d", productId)
}

func (pc *ProductCache) SetProduct(product *entity.Product) error {
	key := pc.getProductKey(product.ID)
	data, err := json.Marshal(product)
	if err != nil {
		return err
	}
	return pc.client.Set(pc.ctx, key, data, time.Hour).Err()
}

func (pc *ProductCache) GetProduct(prodctId int) (*entity.Product, error) {
	key := pc.getProductKey(prodctId)
	data, err := pc.client.Get(pc.ctx, key).Result()
	if err != nil {
		if err == redis.Nil {
			return nil, nil
		}
		return nil, err
	}
	var product entity.Product
	err = json.Unmarshal([]byte(data), &product)
	if err != nil {
		return nil, err
	}
	return &product, nil
}

func (pc *ProductCache) DeleteProduct(productId int) error {
	key := pc.getProductKey(productId)
	return pc.client.Del(pc.ctx, key).Err()
}

func (pc *ProductCache) GetProducts(productIds []int) (map[int]*entity.Product, []int, error) {
	if len(productIds) == 0 {
		return make(map[int]*entity.Product), []int{}, nil
	}

	keys := make([]string, len(productIds))
	for i, id := range productIds {
		keys[i] = pc.getProductKey(id)
	}

	results, err := pc.client.MGet(pc.ctx, keys...).Result()
	if err != nil {
		return nil, productIds, err
	}

	cached := make(map[int]*entity.Product)
	missed := []int{}

	for i, result := range results {
		if result == nil {
			missed = append(missed, productIds[i])
			continue
		}

		var product entity.Product
		if err := json.Unmarshal([]byte(result.(string)), &product); err != nil {
			logx.Errorf("反序列化商品缓存失败: %v", err)
			missed = append(missed, productIds[i])
			continue
		}
		cached[productIds[i]] = &product
	}
	return cached, missed, nil
}
